package com.zhdl.modules.conveyerbelt.web.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.project.common.util.DelayUtil;
import com.zhdl.common.util.WebResult;
import com.zhdl.modules.conveyerbelt.service.ConveyerBeltService;
import com.zhdl.modules.conveyerbelt.web.resp.MemoryInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static com.zhdl.modules.conveyerbelt.service.impl.ConveyerBeltServiceImpl.memoryInfo;

@Slf4j
@RestController
@RequestMapping(path = "/assemblyBolt", produces = MediaType.APPLICATION_JSON_VALUE)
public class ConveyerBeltController {

    /* int open int address int bit */

    /* address/2 = 00 */

    private static final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    private final Map<Integer, SseEmitter> sseEmitters = new ConcurrentHashMap<>();
    private long sseSeq;
    @Resource
    private ConveyerBeltService conveyerBeltService;

    @GetMapping("/writeValue")
    public WebResult<String> writeValue(int address, int bit, int value) {
        conveyerBeltService.writePlcWarnInfo(address, bit, value);
//        DelayUtil.delayedExecution(1000, () -> {
//            assemblyBoltService.writePlcWarnInfo(address,bit,0);
//            log.info("置为0");
//        });
        return WebResult.okResult("写入地址：" + address + "字节：" + bit + "值为：" + value);
    }

    @GetMapping("/writeStartValue")
    public WebResult<String> writeStartValue(int bit, int value) {
        conveyerBeltService.writePlcStartInfo(bit, value);
        DelayUtil.delayedExecution(1000, () -> {
            conveyerBeltService.writePlcStartInfo(bit, 0);
            log.info("置为0");
        });
        return WebResult.okResult("写入地址：" + 0 + "字节：" + bit + "值为：" + value);
    }

    /**
     * 首页数据请求
     */
    @GetMapping(value = "/sse/{id}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter handleSse(@PathVariable Integer id) {
        log.info(id.toString());
        SseEmitter emitter = new SseEmitter();
        sseEmitters.put(id, emitter);
        // 超时移除
        emitter.onTimeout(() -> {
            emitter.complete();
            sseEmitters.remove(id);
        });
        // 完成移除
        emitter.onCompletion(() -> sseEmitters.remove(id));
        // 每一秒发送一条消息
        executorService.scheduleAtFixedRate(() -> {
            ObjectMapper mapper = new ObjectMapper();

            //加载内存数据
            WebResult<MemoryInfo> sseResp = WebResult.okResult(memoryInfo);
            try {
                emitter.send(SseEmitter.event().id(String.valueOf(getSseSeq())).data(mapper.writeValueAsString(sseResp), MediaType.APPLICATION_JSON));
                log.info("send" + sseResp);
            } catch (IOException e) {
                emitter.complete();
            }
        }, 0, 1, TimeUnit.SECONDS);

        return emitter;
    }

    /**
     * 获取SSE序号
     */
    private long getSseSeq() {
        if (sseSeq > 65535L * 65535) sseSeq = 0;
        return sseSeq++;
    }
}
